package com.bifang.common.filter.xss;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

@Component
@WebFilter(filterName = "xssFilter", urlPatterns = "/*")
public class XssFilter implements Filter {
    private static final Set<String> ALLOWED_PATHS =
            Collections.unmodifiableSet(new HashSet<>(Arrays.asList("/ureport")));
    FilterConfig filterConfig = null;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    @Override
    public void destroy() {
        this.filterConfig = null;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 跨域设置
        if (response instanceof HttpServletResponse) {
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
            // 通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。
            httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
            // 通过对 Credentials 参数的设置，就可以保持跨域 Ajax 时的 Cookie
            // 设置了Allow-Credentials，Allow-Origin就不能为*,需要指明具体的url域
            // httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
            // 请求方式
            httpServletResponse.setHeader("Access-Control-Allow-Methods", "*");
            // （预检请求）的返回结果（即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息）
            // 可以被缓存多久
            httpServletResponse.setHeader("Access-Control-Max-Age", "86400");

            // 解决ios12请求兼容 不能使用通配符
            // 首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段
            //            httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
            /** cors modified start* */
            StringBuilder headers = new StringBuilder();
            HttpServletRequest req = (HttpServletRequest) request;
            Enumeration<String> headerNames = req.getHeaders("Access-Control-Request-Headers");
            if (Objects.nonNull(headerNames)) {
                while (headerNames.hasMoreElements()) {
                    headers.append(headerNames.nextElement()).append(",");
                }
            }
            httpServletResponse.setHeader("Access-Control-Allow-Headers", headers.toString());
            /** cors modified end* */
        }
        HttpServletRequest req = (HttpServletRequest) request;
        String path =
                req.getRequestURI()
                        .substring(req.getContextPath().length())
                        .replaceAll("[/]+$", "");
        boolean allowedPath = ALLOWED_PATHS.contains(path);

        if (!allowedPath) {
            chain.doFilter(new XssHttpServletRequestWrapper(req), response);
        }
    }
}
